import os
import pandas as pd
import sys
import logging
from typing import List, Dict, Any

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler(os.path.join('V2', 'process.log'), encoding='utf-8'),
        logging.StreamHandler()
    ]
)
logger = logging.getLogger('ExcelProcessor')

class ExcelProcessor:
    def __init__(self):
        """初始化Excel处理器"""
        self.current_dir = os.getcwd()
        self.data_dir = os.path.join(self.current_dir, 'V2', 'data')
        self.results_dir = os.path.join(self.current_dir, 'V2', 'results')
        self.config_file = os.path.join(self.current_dir, 'V2', '.config')
        
        # 确保目录存在
        os.makedirs(self.data_dir, exist_ok=True)
        os.makedirs(self.results_dir, exist_ok=True)
    
    def merge_excel_files(self) -> pd.DataFrame:
        """
        合并data目录下的所有Excel表格
        
        Returns:
            pd.DataFrame: 合并后的DataFrame
        """
        logger.info("开始合并Excel文件...")
        
        # 获取所有Excel文件
        excel_files = []
        for file in os.listdir(self.data_dir):
            if file.endswith(('.xlsx', '.xls', '.csv')):
                excel_files.append(os.path.join(self.data_dir, file))
        
        if not excel_files:
            logger.warning(f"在目录 {self.data_dir} 中未找到Excel文件")
            return pd.DataFrame()
        
        logger.info(f"找到 {len(excel_files)} 个Excel文件")
        
        # 合并所有文件
        dfs = []
        for file in excel_files:
            try:
                if file.endswith('.csv'):
                    df = pd.read_csv(file, encoding='utf-8')
                else:
                    df = pd.read_excel(file)
                dfs.append(df)
                logger.info(f"成功读取文件: {os.path.basename(file)}, 行数: {len(df)}")
            except Exception as e:
                logger.error(f"读取文件 {os.path.basename(file)} 失败: {str(e)}")
        
        if not dfs:
            logger.error("无法读取任何Excel文件")
            return pd.DataFrame()
        
        # 合并DataFrame
        merged_df = pd.concat(dfs, ignore_index=True)
        logger.info(f"合并完成，总行数: {len(merged_df)}")
        
        return merged_df
    
    def clean_and_transform_data(self, df: pd.DataFrame) -> pd.DataFrame:
        """
        数据清洗和转换
        
        Args:
            df (pd.DataFrame): 原始数据
            
        Returns:
            pd.DataFrame: 清洗后的数据
        """
        logger.info("开始数据清洗和转换...")
        
        if df.empty:
            logger.warning("输入数据为空，无法进行清洗")
            return df
        
        # 创建副本以避免修改原始数据
        cleaned_df = df.copy()
        
        # 根据笔记ID去重
        if '笔记ID' in cleaned_df.columns:
            before_dedup = len(cleaned_df)
            cleaned_df = cleaned_df.drop_duplicates(subset=['笔记ID'], keep='first')
            logger.info(f"去重完成: 从 {before_dedup} 行减少到 {len(cleaned_df)} 行")
        else:
            logger.warning("未找到 '笔记ID' 列，跳过去重")
        
        # 获取当前列顺序
        original_columns = cleaned_df.columns.tolist()
        
        # 检查必要的列是否存在
        required_columns = ['笔记ID', '笔记链接', '笔记类型', '发布时间', '更新时间', 'IP地址', 
                           '博主简介', '笔记话题', '笔记内容', '博主链接', '小红书号']
        
        missing_columns = [col for col in required_columns if col not in original_columns]
        if missing_columns:
            logger.warning(f"缺少以下列: {', '.join(missing_columns)}")
        
        # 构建新的列顺序
        new_columns_order = []
        
        # 1. 首先添加笔记ID
        if '笔记ID' in original_columns:
            new_columns_order.append('笔记ID')
        
        # 2. 添加发布时间
        if '发布时间' in original_columns:
            new_columns_order.append('发布时间')
        
        # 3. 添加笔记类型（在发布时间之后）
        if '笔记类型' in original_columns:
            new_columns_order.append('笔记类型')
        
        # 4. 添加笔记链接（在笔记类型之后）
        if '笔记链接' in original_columns:
            new_columns_order.append('笔记链接')
        
        # 5. 添加其他列，跳过已添加的
        for col in original_columns:
            if col not in new_columns_order and col != '更新时间':
                # 特殊处理：IP地址放在博主简介之后
                if col == 'IP地址' and '博主简介' in original_columns:
                    continue
                # 特殊处理：笔记话题放在笔记内容之后
                if col == '笔记话题' and '笔记内容' in original_columns:
                    continue
                new_columns_order.append(col)
        
        # 插入IP地址到博主简介之后
        if 'IP地址' in original_columns and '博主简介' in original_columns:
            if '博主简介' in new_columns_order:
                idx = new_columns_order.index('博主简介')
                new_columns_order.insert(idx + 1, 'IP地址')
        
        # 插入笔记话题到笔记内容之后
        if '笔记话题' in original_columns and '笔记内容' in original_columns:
            if '笔记内容' in new_columns_order:
                idx = new_columns_order.index('笔记内容')
                new_columns_order.insert(idx + 1, '笔记话题')
        
        # 交换博主链接和小红书号的位置
        if '博主链接' in new_columns_order and '小红书号' in new_columns_order:
            link_idx = new_columns_order.index('博主链接')
            xhs_idx = new_columns_order.index('小红书号')
            new_columns_order[link_idx], new_columns_order[xhs_idx] = new_columns_order[xhs_idx], new_columns_order[link_idx]
        
        # 确保所有列都被包含
        for col in original_columns:
            if col not in new_columns_order and col != '更新时间':
                new_columns_order.append(col)
        
        # 应用新的列顺序
        cleaned_df = cleaned_df[new_columns_order]
        
        # 处理IP地址空白
        if 'IP地址' in cleaned_df.columns:
            cleaned_df['IP地址'] = cleaned_df['IP地址'].fillna('未填写或保密')
            logger.info("IP地址空白值已填充为'未填写或保密'")
        
        # 单独导出博主链接到txt文件
        if '博主链接' in cleaned_df.columns:
            blog_links = cleaned_df['博主链接'].dropna().unique()
            with open(os.path.join(self.results_dir, '博主链接.txt'), 'w', encoding='utf-8') as f:
                for link in blog_links:
                    f.write(f"{link}\n")
            logger.info(f"博主链接已导出到 {os.path.join(self.results_dir, '博主链接.txt')}，共 {len(blog_links)} 个链接")
        
        logger.info("数据清洗和转换完成")
        return cleaned_df
    
    def load_config_fields(self) -> List[str]:
        """
        从.config文件加载配置字段列表
        
        Returns:
            List[str]: 字段列表
        """
        fields = []
        
        if os.path.exists(self.config_file):
            try:
                with open(self.config_file, 'r', encoding='utf-8') as f:
                    for line in f:
                        field = line.strip()
                        if field and not field.startswith('#'):
                            fields.append(field)
                logger.info(f"从 {self.config_file} 加载了 {len(fields)} 个配置字段")
            except Exception as e:
                logger.error(f"读取配置文件失败: {str(e)}")
        else:
            logger.warning(f"配置文件 {self.config_file} 不存在，将创建默认配置")
            # 创建默认配置文件
            default_fields = [
                '笔记ID', '发布时间', '笔记类型', '笔记链接', '笔记标题', '笔记内容',
                '点赞量', '收藏量', '评论量', '分享量', 'IP地址', '博主ID',
                '小红书号', '博主昵称', '笔记话题', '博主简介', '获赞与收藏', '粉丝数'
            ]
            with open(self.config_file, 'w', encoding='utf-8') as f:
                f.write('# 配置字段列表\n')
                for field in default_fields:
                    f.write(f"{field}\n")
            logger.info(f"已创建默认配置文件，包含 {len(default_fields)} 个字段")
            fields = default_fields
        
        return fields
    
    def filter_and_export_basic_table(self, df: pd.DataFrame, fields: List[str]) -> pd.DataFrame:
        """
        根据配置字段列表筛选导出基本表
        
        Args:
            df (pd.DataFrame): 初始数据
            fields (List[str]): 要保留的字段列表
            
        Returns:
            pd.DataFrame: 筛选后的数据
        """
        logger.info("开始筛选导出基本表...")
        
        if df.empty:
            logger.warning("输入数据为空，无法进行筛选")
            return df
        
        # 获取实际存在的字段
        available_fields = [field for field in fields if field in df.columns]
        missing_fields = [field for field in fields if field not in df.columns]
        
        if missing_fields:
            logger.warning(f"数据中缺少以下配置字段: {', '.join(missing_fields)}")
        
        if not available_fields:
            logger.error("没有可用的字段进行筛选")
            return df
        
        # 筛选数据
        filtered_df = df[available_fields]
        logger.info(f"筛选完成，保留了 {len(available_fields)} 个字段")
        
        return filtered_df
    
    def export_to_excel(self, df: pd.DataFrame, filename: str):
        """
        导出DataFrame到Excel文件
        
        Args:
            df (pd.DataFrame): 要导出的数据
            filename (str): 文件名
        """
        if df.empty:
            logger.warning(f"数据为空，无法导出到 {filename}")
            return
        
        try:
            file_path = os.path.join(self.results_dir, filename)
            df.to_excel(file_path, index=False, engine='openpyxl')
            logger.info(f"数据已成功导出到 {file_path}")
        except Exception as e:
            logger.error(f"导出到Excel失败: {str(e)}")
            # 尝试用csv格式作为备选
            try:
                csv_path = os.path.join(self.results_dir, filename.replace('.xlsx', '.csv'))
                df.to_csv(csv_path, index=False, encoding='utf-8-sig')
                logger.info(f"作为备选，数据已导出到CSV文件: {csv_path}")
            except Exception as csv_error:
                logger.error(f"导出到CSV也失败: {str(csv_error)}")

def main():
    """主函数"""
    processor = ExcelProcessor()
    
    try:
        # 步骤1: 合并Excel文件
        merged_df = processor.merge_excel_files()
        
        # 步骤2: 数据清洗并导出为初始表
        cleaned_df = processor.clean_and_transform_data(merged_df)
        processor.export_to_excel(cleaned_df, '初始表.xlsx')
        
        # 步骤3: 根据配置字段列表筛选导出基本表
        config_fields = processor.load_config_fields()
        basic_df = processor.filter_and_export_basic_table(cleaned_df, config_fields)
        processor.export_to_excel(basic_df, '基本表.xlsx')
        
        logger.info("所有处理完成!")
        print("\n处理完成!")
        print(f"1. 合并了多个Excel文件")
        print(f"2. 数据清洗后导出到: {os.path.join(processor.results_dir, '初始表.xlsx')}")
        print(f"3. 博主链接导出到: {os.path.join(processor.results_dir, '博主链接.txt')}")
        print(f"4. 基本表导出到: {os.path.join(processor.results_dir, '基本表.xlsx')}")
        
    except Exception as e:
        logger.error(f"处理过程中出错: {str(e)}")
        print(f"错误: {str(e)}")
        import traceback
        traceback.print_exc()

if __name__ == "__main__":
    main()